package org.maitaole.advisor;

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.maitaole.annotation.ProcessLogInfo;
import org.maitaole.commons.Constant;
import org.maitaole.entity.ProcessLog;
import org.maitaole.entity.SysUser;
import org.maitaole.service.IProcessLogService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

// https://blog.csdn.net/lcgoing/article/details/88537836
@Aspect
@Component
//@EnableAspectJAutoProxy(proxyTargetClass=true)  //开启 AspectJ 的注解，与配置上 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 效果一直
public class ProcessLogAdvisor {

    @Resource
    private IProcessLogService processLogService;

    /**
     * 表示如果某个个方法头顶加了  @ProcessLog 这个注解，该方法才会接受到用户的通知
     */
    @Around("@annotation(org.maitaole.annotation.ProcessLogInfo)")
    public Object before(ProceedingJoinPoint jp) throws Throwable {
        MethodSignature ms = (MethodSignature)jp.getSignature();
        Method method = ms.getMethod();

        Class<?> clazz = method.getDeclaringClass();
        String className = clazz.getName(); // 获取类名

        String methodName = method.getName(); // 获取到方法名

        ProcessLogInfo pli = method.getAnnotation(ProcessLogInfo.class);
        String processInfo = pli.value(); // 获取到注解的内容

        // 获取 Request
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        HttpSession session = request.getSession();
        SysUser sysUser = (SysUser) session.getAttribute(Constant.USER_INFO_ATTR);
        String username = sysUser.getUsername(); // 获取用户名

        Object[] args = jp.getArgs();   // 参数值
        Parameter[] parameters = method.getParameters();  // 获取所有的参数

        Map<String, Object> paramsInfo = new HashMap<>();

        for(int i = 0; i < parameters.length; i++) {
            String paramName = parameters[i].getName(); // 获取参数值
            Object paramValue = args[i];
            paramsInfo.put(paramName, paramValue);
        }

        String paramsInfoJson = JSONObject.toJSONString(paramsInfo);

        ProcessLog pl = new ProcessLog();
        pl.setUsername(username);
        pl.setClassName(className);
        pl.setMethodName(methodName);
        pl.setCreateTime(new Date());
        pl.setProcessInfo(processInfo);
        pl.setParamsInfo(paramsInfoJson);

        processLogService.saveProcessLog(pl);

        return jp.proceed();
    }
}
